package com.brutal.minigames.gop;

import java.awt.Point;
import java.awt.Polygon;
import java.util.LinkedList;

import com.rsbuddy.script.methods.Calculations;
import com.rsbuddy.script.methods.Menu;
import com.rsbuddy.script.methods.Mouse;
import com.rsbuddy.script.methods.Players;
import com.rsbuddy.script.util.Random;
import com.rsbuddy.script.wrappers.GameObject;
import com.rsbuddy.script.wrappers.Locatable;
import com.rsbuddy.script.wrappers.Model;
import com.rsbuddy.script.wrappers.Npc;
import com.rsbuddy.script.wrappers.Tile;

public abstract class Task {

	public abstract boolean isValid();

	public abstract void execute();

	public abstract String getStatus();

	protected static void sleep(final int time) {
		com.rsbuddy.script.task.Task.sleep(time);
	}

	protected static void sleep(final int min, final int max) {
		com.rsbuddy.script.task.Task.sleep(min, max);
	}

	protected static Tile getClosestTile(final Tile tile) {
		final Tile me = Players.getLocal().getLocation();
		final Tile half = new Tile((me.getX() + tile.getLocation().getX()) / 2,
				(me.getY() + tile.getLocation().getY()) / 2);
		final Tile close = new Tile(
				(half.getX() + tile.getLocation().getX()) / 2,
				(half.getY() + tile.getLocation().getY()) / 2);
		return close;
	}

	protected static boolean interact(final GameObject go, final String action) {
		if (go == null) {
			return false;
		}
		final Model model = go.getModel();
		if (model == null) {
			if (go.getLocation() == null) {
				return false;
			}
			return interact(go.getLocation(), action);
		}
		return interact(model, action);
	}

	protected static boolean interact(final Npc npc, final String action) {
		if (npc == null) {
			return false;
		}
		final Model model = npc.getModel();
		if (model == null) {
			if (npc.getLocation() == null) {
				return false;
			}
			return interact(npc.getLocation(), action);
		}
		return interact(model, action);
	}

	protected static boolean interact(final Locatable loc, final String action) {
		if (loc == null) {
			return false;
		}
		if (loc.getLocation() == null) {
			return false;
		}
		return interact(loc.getLocation(), action);
	}

	private static boolean interact(final Model model, final String action) {
		if (model == null) {
			return false;
		}
		Point p = getRandomPoint(model);
		if (p == null || !Calculations.isPointOnScreen(p)
				|| p == new Point(-1, -1)) {
			return false;
		}
		final int speed = Mouse.getSpeed();
		Mouse.setSpeed(Random.nextInt(5, 11));
		for (int i = 0; i < 50 && model != null
				&& Calculations.isPointOnScreen(p); i++) {
			p = getRandomPoint(model);
			if (p == null) {
				return false;
			}
			Mouse.move(p);
			if (Menu.contains(action)) {
				return Menu.click(action);
			}
		}
		Mouse.setSpeed(speed);
		return false;
	}

	protected static boolean interact(final Tile tile, final String action) {
		if (tile == null) {
			return false;
		}
		Point p = getRandomPoint(tile);
		if (p == null || !Calculations.isPointOnScreen(p)
				|| p == new Point(-1, -1)) {
			return false;
		}
		final int speed = Mouse.getSpeed();
		Mouse.setSpeed(Random.nextInt(5, 11));
		for (int i = 0; i < 50 && tile != null
				&& Calculations.isPointOnScreen(p); i++) {
			p = getRandomPoint(tile);
			if (p == null) {
				return false;
			}
			Mouse.move(p);
			if (Menu.contains(action)) {
				return Menu.click(action);
			}
		}
		Mouse.setSpeed(speed);
		return false;
	}

	protected static boolean interact(final Tile tile, final int dX,
			final int dY, final int height, final String action) {
		if (tile == null) {
			return false;
		}
		Point p = Calculations.tileToScreen(tile, dX, dY, height);
		if (p == null || !Calculations.isPointOnScreen(p)
				|| p == new Point(-1, -1)) {
			return false;
		}
		final int speed = Mouse.getSpeed();
		Mouse.setSpeed(Random.nextInt(5, 11));
		for (int i = 0; i < 50 && tile != null
				&& Calculations.isPointOnScreen(p); i++) {
			p = getRandomPoint(tile);
			if (p == null) {
				return false;
			}
			Mouse.move(p);
			if (Menu.contains(action)) {
				return Menu.click(action);
			}
		}
		Mouse.setSpeed(speed);
		return false;
	}

	protected static Point getModelCenter(final Model model) {
		if (model == null) {
			return null;
		}
		final Polygon[] polygons = model.getTriangles();
		final LinkedList<Point> points = new LinkedList<Point>();
		for (Polygon polygon : polygons) {
			for (int i = 0; i < polygon.npoints; i++) {
				points.add(new Point(polygon.xpoints[i], polygon.ypoints[i]));
			}
		}
		int xTotal = 0;
		int yTotal = 0;
		for (Point p : points) {
			xTotal += p.x;
			yTotal += p.y;
		}
		if (points.size() <= 5) {
			return null;
		}
		return new Point(xTotal / points.size(), yTotal / points.size());
	}

	protected static Point getRandomPoint(final Model model) {
		final Polygon[] triangles = model.getTriangles();
		if (triangles.length == 0) {
			return null;
		}
		final Polygon p = triangles[Random.nextInt(0, triangles.length)];
		return getRandomPoint(p);
	}

	protected static Point getRandomPoint(final Tile tile) {
		final Point bl = Calculations.tileToScreen(tile, 0, 0, 0), br = Calculations
				.tileToScreen(tile, 1, 0, 0), tr = Calculations.tileToScreen(
				tile, 1, 1, 0), tl = Calculations.tileToScreen(tile, 0, 1, 0);
		final Polygon p = new Polygon(new int[] { bl.x, br.x, tr.x, tl.x },
				new int[] { bl.y, br.y, tr.y, tl.y }, 4);
		return getRandomPoint(p);
	}

	protected static Point getRandomPoint(final Polygon p) {
		double a = Math.random();
		double b = Math.random();
		if (a + b >= 1) {
			a = 1 - a;
			b = 1 - b;
		}
		final double c = 1 - a - b;
		return new Point((int) (a * p.xpoints[0] + b * p.xpoints[1] + c
				* p.xpoints[2]), (int) (a * p.ypoints[0] + b * p.ypoints[1] + c
				* p.ypoints[2]));
	}
}
